package engine.time;

import creatures.Creature;

/**
 * <b>Note: this class has a natural ordering that is inconsistent with equals.</b>
 * <p>
 * A container that holds a creature and the time when it is next scheduled to act.
 * 
 * @author Kyle_Solo
 */
class TimeEntry implements Comparable<TimeEntry> {
	private final Creature creature;
	private long time;

	public TimeEntry(Creature creature, long time) {
		this.creature = creature;
		setTime(time);
	}

	/**
	 * @param amount
	 *            the amount of time to delay this TimeEntry
	 */
	public void add(int amount) {
		setTime(getTime() + amount);
	}

	@Override
	public int compareTo(TimeEntry o) {
		/*
		 * This method determines the sort order for TimeEntries. It sorts first by the scheduled
		 * time (lowest time first), then by each Creatue's speed (highest speed first), then by
		 * each Creature's ID (lowest ID first).
		 */
		int diff;
		if (getTime() == o.getTime()) {
			/*
			 * Tragically, they are scheduled to act at the same time must have the one with the
			 * higher speed go first
			 */
			diff = o.creature.getSpeed() - creature.getSpeed();
			if (diff == 0) {
				/*
				 * Tragically yet again, they have the same speeds for the sake of consistency, the
				 * one with the lower id will go first
				 */
				diff = creature.ID - o.creature.ID;
			}
		} else {
			// they act at different times
			if (getTime() < o.getTime()) {
				return -1;
			} else {
				return 1;
			}
		}
		return diff;
	}

	@Override
	public boolean equals(Object obj) {
		if (obj.getClass() == TimeEntry.class) {
			TimeEntry te = (TimeEntry) obj;
			/*
			 * Two TimeEntry are only equal if they contain the same creature
			 */
			return (te.creature == creature);

		}
		// A TimeEntry equals a creature if it contains the creature
		return creature == obj;
	}

	/**
	 * @return this TimeEntry's creature
	 */
	public Creature getCreature() {
		return creature;
	}

	/**
	 * Gets the time for this TimeEntry
	 * 
	 * @return time
	 */
	public long getTime() {
		return time;
	}

	/**
	 * Sets this TimeEntry's time value
	 * 
	 * @param time
	 *            the time to set
	 */
	public void setTime(long time) {
		this.time = time;
	}

	@Override
	public String toString() {
		return creature.toString() + " at time " + getTime();
	}
}